<title>AppRTC look for RTCMultiConnection Demo | Muaz Khan</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">

<script>
    if(!location.hash.replace('#', '').length) {
        location.href = location.href.split('#')[0] + '#' + (Math.random() * 100).toString().replace('.', '');
        location.reload();
    }
</script>

<meta name="description" content="AppRTC like RTCMultiConnection demo where styles and layout is taken from AppRTC demo." />
<meta name="keywords" content="AppRTC,RTCMultiConnection,AppRTC-Look,WebRTC" />

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
<meta name="author" content="Muaz Khan">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<script src="https://cdn.webrtc-experiment.com/socket.io.js"></script>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="https://cdn.webrtc-experiment.com/CodecsHandler.js"></script>
<script src="https://cdn.webrtc-experiment.com/IceServersHandler.js"></script>
<script src="https://cdn.webrtc-experiment.com/RTCMultiConnection.js"></script>

<style>
body,
html {
    background: black;
    text-align: center;
    color: white;
    overflow: hidden;
}

.local-media,
.remote-media {
    max-width: 100%;
    max-height: 70%;
}

.local-media-small,
.remote-media-small {
    width: 20%;
    position: fixed;
    bottom: 0;
    left: 0;
}

button {
    display: inline-block;
    outline: 0;
    color: white;
    background: #4472b9;
    white-space: nowrap;
    border: 5px solid #4472b9 !important;
    font-family: 'Gotham Rounded A', 'Gotham Rounded B', sans-serif;
    font-weight: 500;
    font-style: normal;
    padding: 9px 16px !important;
    line-height: 1.4;
    position: relative;
    border-radius: 10px;
    -webkit-box-shadow: 5px 5px 0 0 rgba(0, 0, 0, 0.15);
    box-shadow: 5px 5px 0 0 rgba(0, 0, 0, 0.15);
    -webkit-transition: 0.1s;
    transition: 0.1s;
}

button:hover,
button:active,
button:focus {
    background: #04C;
}

button[disabled] {
    background: transparent;
    border-color: rgb(83, 81, 81);
    color: rgb(139, 133, 133);
}

#container {
    -webkit-perspective: 1000;
    background-color: #000000;
    height: 100%;
    margin: 0px auto;
    position: absolute;
    width: 100%;
}

#card {
    -webkit-transform-style: preserve-3d;
    -webkit-transition-duration: 2s;
    -webkit-transition-property: rotation;
}

#local {
    -webkit-backface-visibility: hidden;
    -webkit-transform: scale(-1, 1);
    position: absolute;
    width: 100%;
}

#remote {
    -webkit-backface-visibility: hidden;
    -webkit-transform: rotateY(180deg);
    position: absolute;
    width: 100%;
}

#mini {
    /* -webkit-transform: scale(-1, 1); */
    
    bottom: 0;
    height: 30%;
    opacity: 1.0;
    position: absolute;
    right: 4px;
    width: 30%;
}

#localVideo {
    -webkit-transition-duration: 2s;
    -webkit-transition-property: opacity;
    height: 100%;
    opacity: 0;
    width: 100%;
}

#remoteVideo {
    -webkit-transition-duration: 2s;
    -webkit-transition-property: opacity;
    height: 100%;
    opacity: 0;
    width: 100%;
}

#miniVideo,
.other-videos {
    -webkit-transition-duration: 2s;
    -webkit-transition-property: opacity;
    height: 100%;
    opacity: 0;
    width: 100%;
}

#footer {
    background-color: #3F3F3F;
    bottom: 0;
    color: rgb(255, 255, 255);
    font-size: 13px;
    font-weight: bold;
    height: 28px;
    line-height: 28px;
    position: absolute;
    text-align: center;
    width: 100%;
}

#hangup {
    background-color: #808080;
    border-color: #FFFFFF;
    border-style: solid;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: bold;
    height: 24px;
    margin: 2px;
    width: 128px;
}
</style>

<button id="open-room" style="position: fixed; left: 45%; right: 45%; z-index: 100000;">Open Room</button>

<div id="container" ondblclick="enterFullScreen()">
    <div id="card">
        <div id="local">
            <video id="localVideo" autoplay="autoplay" muted="true" />
        </div>
        <div id="remote">
            <video id="remoteVideo" autoplay="autoplay"></video>
            <div id="mini">
                <video id="miniVideo" autoplay="autoplay" muted="true" />
            </div>
        </div>
    </div>
</div>

<script>
// initializing the constructor
var connection = new RTCMultiConnection();

// https://github.com/muaz-khan/WebRTC-Experiment/tree/master/socketio-over-nodejs
var SIGNALING_SERVER = 'https://socketio-over-nodejs2.herokuapp.com:443/';
connection.openSignalingChannel = function(config) {
    var channel = config.channel || connection.channel || 'default-namespace';
    var sender = Math.round(Math.random() * 9999999999) + 9999999999;

    io.connect(SIGNALING_SERVER).emit('new-channel', {
        channel: channel,
        sender: sender
    });

    var socket = io.connect(SIGNALING_SERVER + channel);
    socket.channel = channel;

    socket.on('connect', function() {
        if (config.callback) config.callback(socket);
    });

    socket.send = function(message) {
        socket.emit('message', {
            sender: sender,
            data: message
        });
    };

    socket.on('message', config.onmessage);
};

// some booleans to override defaults
connection.preventSSLAutoAllowed = false;
connection.autoReDialOnFailure = true;
connection.setDefaultEventsForMediaElement = false;

// setting type of media connection
connection.session = {
    audio: true,
    video: true
};

// DOM objects
var localVideo = document.getElementById('localVideo');
var miniVideo = document.getElementById('miniVideo');
var remoteVideo = document.getElementById('remoteVideo');
var card = document.getElementById('card');
var containerDiv;

var main = document.querySelector('#main');
var smaller = document.querySelector('#smaller');

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

if (navigator.mozGetUserMedia) {
    console.log("This appears to be Firefox");

    webrtcDetectedBrowser = "firefox";

    webrtcDetectedVersion =
        parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1]);

    // The RTCPeerConnection object.
    RTCPeerConnection = mozRTCPeerConnection;

    // The RTCSessionDescription object.
    RTCSessionDescription = mozRTCSessionDescription;

    // The RTCIceCandidate object.
    RTCIceCandidate = mozRTCIceCandidate;

    // Get UserMedia (only difference is the prefix).
    // Code from Adam Barth.
    getUserMedia = navigator.mozGetUserMedia.bind(navigator);

    // Attach a media stream to an element.
    attachMediaStream = function(element, stream) {
        console.log("Attaching media stream");
        element.mozSrcObject = stream;
        element.play();
    };

    reattachMediaStream = function(to, from) {
        console.log("Reattaching media stream");
        to.mozSrcObject = from.mozSrcObject;
        to.play();
    };

    // Fake get{Video,Audio}Tracks
    MediaStream.prototype.getVideoTracks = function() {
        return [];
    };

    MediaStream.prototype.getAudioTracks = function() {
        return [];
    };
} else if (navigator.webkitGetUserMedia) {
    console.log("This appears to be Chrome");

    webrtcDetectedBrowser = "chrome";
    webrtcDetectedVersion =
        parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]);

    // The RTCPeerConnection object.
    RTCPeerConnection = webkitRTCPeerConnection;

    // Get UserMedia (only difference is the prefix).
    // Code from Adam Barth.
    getUserMedia = navigator.webkitGetUserMedia.bind(navigator);

    // Attach a media stream to an element.
    attachMediaStream = function(element, stream) {
        if (typeof element.srcObject !== 'undefined') {
            element.srcObject = stream;
        } else if (typeof element.mozSrcObject !== 'undefined') {
            element.mozSrcObject = stream;
        } else if (typeof element.src !== 'undefined') {
            element.src = URL.createObjectURL(stream);
        } else {
            console.log('Error attaching stream to element.');
        }
    };

    reattachMediaStream = function(to, from) {
        to.src = from.src;
    };

    // The representation of tracks in a stream is changed in M26.
    // Unify them for earlier Chrome versions in the coexisting period.
    if (!webkitMediaStream.prototype.getVideoTracks) {
        webkitMediaStream.prototype.getVideoTracks = function() {
            return this.videoTracks;
        };
        webkitMediaStream.prototype.getAudioTracks = function() {
            return this.audioTracks;
        };
    }

    // New syntax of getXXXStreams method in M26.
    if (!webkitRTCPeerConnection.prototype.getLocalStreams) {
        webkitRTCPeerConnection.prototype.getLocalStreams = function() {
            return this.localStreams;
        };
        webkitRTCPeerConnection.prototype.getRemoteStreams = function() {
            return this.remoteStreams;
        };
    }
} else {
    console.log("Browser does not appear to be WebRTC-capable");
}

// onstream event; fired both for local and remote videos
var numberOfRemoteVideos = 0;
connection.onstream = function(e) {
    if (e.type == 'local') {
        localStream = e.stream;
        attachMediaStream(localVideo, e.stream);
        localVideo.muted = true;
        localVideo.style.opacity = 1;
    }

    if (e.type == 'remote') numberOfRemoteVideos++;

    if (e.type == 'remote' && numberOfRemoteVideos == 1) {
        remoteStream = e.stream;
        reattachMediaStream(miniVideo, localVideo);
        miniVideo.muted = true;
        attachMediaStream(remoteVideo, e.stream);
        waitForRemoteVideo();

        remoteVideo.setAttribute('data-id', e.userid);
        miniVideo.setAttribute('data-id', connection.userid);
    }

    if (e.type == 'remote' && numberOfRemoteVideos == 2) {
        appendVideo(e, 'opacity: 1;position: fixed;bottom: 0;z-index: 1;width: 32%;');
    }

    if (e.type == 'remote' && numberOfRemoteVideos == 3) {
        appendVideo(e, 'opacity: 1;position: fixed;top: 0;z-index: 1;width: 32%;');
    }

    if (e.type == 'remote' && numberOfRemoteVideos == 4) {
        appendVideo(e, 'opacity: 1;position: fixed;top: 0;z-index: 1;width: 32%;right:0;');
    }

    if (e.type == 'local') {
        document.getElementById('open-room').style.display = 'none';
    }
};

function appendVideo(e, style) {
    createVideoContainer(e, style, function(div) {
        var video = document.createElement('video');
        video.className = 'other-videos';
        video.setAttribute('style', 'height:auto;opacity:1;');
        video.id = e.userid;
        video.srcObject = stream;

        try {
            video.setAttributeNode(document.createAttribute('autoplay'));
            video.setAttributeNode(document.createAttribute('playsinline'));
            video.setAttributeNode(document.createAttribute('controls'));
        } catch (e) {
            video.setAttribute('autoplay', true);
            video.setAttribute('playsinline', true);
            video.setAttribute('controls', true);
        }
    
        div.appendChild(video);
    });
}

function createVideoContainer(e, style, callback) {
    var div = document.createElement('div');
    div.setAttribute('style', style || 'float:left;opacity: 1;width: 32%;');
    remote.insertBefore(div, remote.firstChild);
    if (callback) callback(div);
}

// if user left
connection.onleave = function(e) {
    var video = document.getElementById(e.userid);

    if (numberOfRemoteVideos == 1) {
        transitionToWaiting();
    } else if (video && video.parentNode && video.parentNode.parentNode) {
        numberOfRemoteVideos--;
        video.parentNode.parentNode.removeChild(video.parentNode);
    }
};

function waitForRemoteVideo() {
    // Call the getVideoTracks method via adapter.js.
    var videoTracks = remoteStream.getVideoTracks();
    if (videoTracks.length === 0 || remoteVideo.currentTime > 0) {
        transitionToActive();
    } else {
        setTimeout(waitForRemoteVideo, 100);
    }
}

function transitionToActive() {
    remoteVideo.style.opacity = 1;
    card.style.webkitTransform = 'rotateY(180deg)';
    setTimeout(function() {
        localVideo.src = '';
    }, 500);
    setTimeout(function() {
        miniVideo.style.opacity = 1;
    }, 1000);
    // Reset window display according to the aspectRatio of remote video.
    window.onresize();
}

function transitionToWaiting() {
    card.style.webkitTransform = 'rotateY(0deg)';
    setTimeout(function() {
        localVideo.src = miniVideo.src;
        localVideo.muted = true;
        miniVideo.src = '';
        remoteVideo.src = '';

        localVideo.style.opacity = 1;
    }, 500);
    miniVideo.style.opacity = 0;
    remoteVideo.style.opacity = 0;
}


// Set the video displaying in the center of window.
window.onresize = function() {
    var aspectRatio;
    if (remoteVideo.style.opacity === '1') {
        aspectRatio = remoteVideo.videoWidth / remoteVideo.videoHeight;
    } else if (localVideo.style.opacity === '1') {
        aspectRatio = localVideo.videoWidth / localVideo.videoHeight;
    } else {
        return;
    }

    var innerHeight = this.innerHeight;
    var innerWidth = this.innerWidth;
    var videoWidth = innerWidth < aspectRatio * window.innerHeight ?
        innerWidth : aspectRatio * window.innerHeight;
    var videoHeight = innerHeight < window.innerWidth / aspectRatio ?
        innerHeight : window.innerWidth / aspectRatio;
    containerDiv = document.getElementById('container');
    containerDiv.style.width = videoWidth + 'px';
    containerDiv.style.height = videoHeight + 'px';
    containerDiv.style.left = (innerWidth - videoWidth) / 2 + 'px';
    containerDiv.style.top = (innerHeight - videoHeight) / 2 + 'px';
};

function enterFullScreen() {
    container.webkitRequestFullScreen();
}

// connecting to signaling medium
connection.connect();

document.getElementById('open-room').onclick = function() {
    this.disabled = true;

    // starting a new room
    connection.open();
};
</script>